#pragma once
#include <windows.h>
#include <cesync.h>

/*
 *  ============ Required OLE implementation for InProc servers ======================
 */
// CClassFactory object creates CStore objects

class CClassFactory : public IClassFactory 
{
private:
    LONG    m_cRef; 

public:
    CClassFactory( void ) : m_cRef( 0 ) {};

    virtual STDMETHODIMP            QueryInterface( REFIID iid, LPVOID* ppv);
    virtual STDMETHODIMP_(ULONG)    AddRef(); 
    virtual STDMETHODIMP_(ULONG)    Release();

    // IClassFactory members
    virtual STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, LPVOID*);
    virtual STDMETHODIMP LockServer(BOOL);
};

class CStore;

/*
 * === Handler to serialize/deserialize objects ====================
 */
class CDataHandler : public IReplObjHandler
{
public:
	CDataHandler(CStore*);
	~CDataHandler();
	// ******** IUnknown methods **************
	STDMETHODIMP_(ULONG)    AddRef( void );
	STDMETHODIMP_(ULONG)    Release( void );
	STDMETHODIMP            QueryInterface( REFIID riid, void **ppvObject );

	// ******** IReplObjHandler methods **************
	STDMETHODIMP Setup( PREPLSETUP pSetup );
	STDMETHODIMP Reset( PREPLSETUP pSetup );

	STDMETHODIMP GetPacket( LPBYTE *lppbData,  DWORD *pcbData, DWORD cbRecommend );
	STDMETHODIMP SetPacket( LPBYTE lpbData, DWORD cbData );
	STDMETHODIMP DeleteObj( PREPLSETUP pSetup );

private:
	long        m_cRef;
	CStore      *m_pStore;
	PREPLSETUP  m_pWriteSetup, m_pReadSetup;
};

class CStore: public IReplStore2
{
public:
	CStore( LPUNKNOWN );
	~CStore();

	// ******** IUnknown methods **************
	STDMETHODIMP            QueryInterface(REFIID riid, void **ppvObject);
	STDMETHODIMP_(ULONG)    AddRef(void);
	STDMETHODIMP_(ULONG)    Release(void);

	// ******** IReplStore methods **************
	STDMETHODIMP        Initialize( IReplNotify *, UINT uFlags );
	STDMETHODIMP        GetStoreInfo( PSTOREINFO pStoreInfo );
	STDMETHODIMP        ReportStatus( HREPLFLD hFolder, HREPLITEM hItem, UINT uStatus, UINT uReserved );
	STDMETHODIMP_(int)  CompareStoreIDs( LPBYTE lpbID1, UINT cbID1, LPBYTE lpbID2, UINT cbID2 );

	// object related routines
	STDMETHODIMP_(int)  CompareItem( HREPLITEM hItem1, HREPLITEM hItem2 );
	STDMETHODIMP_(BOOL) IsItemChanged( HREPLFLD hFolder, HREPLITEM hItem, HREPLITEM hItemComp );
	STDMETHODIMP_(BOOL) IsItemReplicated( HREPLFLD hFolder, HREPLITEM hItem );
	STDMETHODIMP_(void) UpdateItem( HREPLFLD hFolder, HREPLITEM hItemDst, HREPLITEM hItemSrc );

	// folder related routines
	STDMETHODIMP        GetFolderInfo( LPCSTR lpszName,  HREPLFLD *phFolder, IUnknown **ppObjHandler );
	STDMETHODIMP        IsFolderChanged( HREPLFLD hFolder, BOOL *pfChanged );

	// enumeration of folder objects
	STDMETHODIMP        FindFirstItem( HREPLFLD hFolder,  HREPLITEM *phItem, BOOL *pfExist );    // get first object the folder
	STDMETHODIMP        FindNextItem( HREPLFLD hFolder,  HREPLITEM *phItem, BOOL *pfExist );     // get next object the folder
	STDMETHODIMP        FindItemClose( HREPLFLD hFolder );                                    // done enumerating

	// STD management routines
	STDMETHODIMP_(UINT)     ObjectToBytes( HREPLOBJ hObject, LPBYTE lpb );
	STDMETHODIMP_(HREPLOBJ) BytesToObject( LPBYTE lpb, UINT cb );
	STDMETHODIMP_(void)     FreeObject( HREPLOBJ hObject );
	STDMETHODIMP_(BOOL)     CopyObject( HREPLOBJ hObjSrc, HREPLOBJ hObjDst );
	STDMETHODIMP            IsValidObject( HREPLFLD hFolder, HREPLITEM hObject, UINT uFlags );

	// UI related routines
	STDMETHODIMP        ActivateDialog( UINT uDlg, HWND hwndParent, HREPLFLD hFolder, IEnumReplItem *penum );
	STDMETHODIMP        GetObjTypeUIData( HREPLFLD hFolder, POBJUIDATA pData );
	STDMETHODIMP        GetConflictInfo( PCONFINFO pConfInfo );
	STDMETHODIMP        RemoveDuplicates( LPCSTR, UINT );

	// ******** IReplStore2 methods **************
	STDMETHODIMP        DoOptionsDialog(HWND hwndParent, LPCSTR lpszObjType, IReplNotify * pntfy);
private:
	LONG m_cRef;
	LPUNKNOWN m_pUnknown;
	CDataHandler *m_pObjHandler;
};